/**
 * @FileName: semaphore.cc
 * @Author: 李波(Edwin Lee)
 * @Date: 2024-04-16 14:44:17
 * @Version: 1.0
 * @Description: 
 */
#include <cstdio>
#include <pthread.h>
#include <unistd.h>
#include <queue>
#include <semaphore.h>
#include <sys/syscall.h>

using namespace std;

queue<int> qint;  // 用deque容器做缓存。

sem_t sem;
pthread_mutex_t mutex;
void  incache();      // 生产者、数据入dui 
void *outcache(void *arg);   // 消费者、数据出队线程的主函数。

int main()
{
	printf("程序开始\n");
	sem_init(&sem,0, 0);
  // 创建三个消费者线程。
  pthread_t thid1,thid2,thid3;
  pthread_create(&thid1,NULL,outcache,NULL);
  pthread_create(&thid2,NULL,outcache,NULL);
  pthread_create(&thid3,NULL,outcache,NULL);
	printf("创建三条线程成功\n");
  for(int i=0; i<5; ++i)
	{
		incache();
	  sleep(5);
	}
	pthread_cancel(thid1);
	pthread_cancel(thid2);
	pthread_cancel(thid3);
  pthread_join(thid1,NULL);
  pthread_join(thid2,NULL);
  pthread_join(thid3,NULL);


  return 0;
}

void incache()       // 生产者、数据入队。
{
  static int mesgid=1;  // 消息的计数器。

  pthread_mutex_lock(&mutex);    // 给缓存队列加锁。

  //  生产数据，放入缓存队列。
	qint.push(mesgid++);
	qint.push(mesgid++);
	qint.push(mesgid++);
	qint.push(mesgid++);

  pthread_mutex_unlock(&mutex);  // 给缓存队列解锁。
  //pthread_cond_signal(&cond);    // 发送条件信号，激活一个线程。
	printf("生产了4条数据\n");
	sem_post(&sem);
	sem_post(&sem);
	sem_post(&sem);
	sem_post(&sem);
}

void *outcache(void *arg)    // 消费者、数据出队线程的主函数。
{
	int tmp=0;
	printf("pid=%ld 线程开始\n",::syscall(SYS_gettid));
  while (true)
  {
    pthread_mutex_lock(&mutex);  // 给缓存队列加锁。

    // 如果缓存队列为空，等待，用while防止条件变量虚假唤醒。
    while (qint.empty())
    {
			pthread_mutex_unlock(&mutex);
			sem_wait(&sem);
			pthread_mutex_lock(&mutex);
    }
    // 从缓存队列中获取第一条记录，然后删除该记录。
		tmp = qint.front();
    qint.pop();

    pthread_mutex_unlock(&mutex);  // 给缓存队列解锁。

    // 以下是处理业务的代码。
    printf("pid=%ld,mesgid=%d\n",::syscall(SYS_gettid),tmp);
    usleep(100);
  }
}

